/**
 * All Rights Reserved , Copyright (C) 2020 , 青岛鼎信通讯股份有限公司
 * <p>
 * BaseChangeLogService
 * 变更记录表
 * <p>
 * 修改纪录
 * 2020-12-01 版本：1.0 zhanglongfei 创建。
 *
 * @version 版本：1.0
 * @author 作者：zhanglongfei
 * 创建日期：2020-12-01
 */
package com.topscomm.base.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import cn.hutool.core.convert.Convert;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.configurationprocessor.json.JSONArray;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.topscomm.base.BaseEntity;
import com.topscomm.base.BaseSystemConst;
import com.topscomm.base.BaseSystemConst.BaseLogOperateTypeEnum;
import com.topscomm.base.pojo.BaseChangeLogEntity;
import com.topscomm.base.service.IBaseChangeLogService;
import com.topscomm.base.service.IBasePropertyService;
import com.topscomm.base.service.impl.auto.BaseChangeLogServiceAuto;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.BasicService;
import com.topscomm.basic.IBasicDao;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.SpringUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.common.DatacodeCache;

@Service(value = "baseChangeLogService")
@Scope(value = "singleton")
public class BaseChangeLogService extends BaseChangeLogServiceAuto implements IBaseChangeLogService {
	@Autowired
	private IBasePropertyService basePropertyService;
	@Autowired
	protected DatacodeCache datacodeCache;
	// 在baseproperty中使用属性的范围
	private static final String BASEPROPERTYSCOPE = "changelog";
	private static final Map<String, String> OPERATION_NAME_MAP = new HashMap<>();
	static {
		OPERATION_NAME_MAP.put(BaseSystemConst.BaseLogOperateTypeEnum.Add, "新增");
		OPERATION_NAME_MAP.put(BaseSystemConst.BaseLogOperateTypeEnum.Edit, "修改");
		OPERATION_NAME_MAP.put(BaseSystemConst.BaseLogOperateTypeEnum.Del, "删除");
	}

	/**
	 * @param inputMap
	 *            { "sourceid": 1, //数据id 必填 "sourcetype": "CpCustomerCompany",
	 *            //数据表名称 必填 "newmap": { //新数据 必填 "name": "qwe", "code": "222",
	 *            "tel": "33333" }, "oldmap": { //旧数据 必填 "name": "qwe", "code":
	 *            "222", "tel": "33333" }, "baselogoperatetype": "add" //操作类型 必填
	 *            类型见枚举BaseLogOperateTypeEnum "topsourcetype": "CpCustomerCompany"
	 *            //所属来源类型 目前类型有客户推进、企业客户、个人客户 "topsourceid": "code111" //所属来源类型主键
	 *            企业客户、个人客户使用code }
	 * @return java.util.Map<java.lang.String, java.lang.Object>
	 * @description: 添加客户变更记录
	 * @author: wangxinhua
	 * @date: 2020/12/1 18:38
	 * @modify:
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String insertChangeLog(Map<String, Object> inputMap) {
		// 新版本号，未更新则返回空，更新则返回版本号
		String newVersion = "";
		try {
			// 验证参数
			Map<String, Object> validateMap = validateParams(inputMap);
			if (validateMap.get("success").equals(false)) {
				return newVersion;
			}
			// 整理变量类型
			Map<String, Object> newMap = (Map<String, Object>) inputMap.get("newmap");
			Map<String, Object> oldMap = (Map<String, Object>) inputMap.get("oldmap");
			String sourceType = inputMap.get("sourcetype").toString();
			String sourceId = inputMap.get("sourceid").toString();
			String baseLogOperateType = inputMap.get("baselogoperatetype").toString();
			String topsourcetype = inputMap.get("topsourcetype").toString();
			String topsourceid = inputMap.get("topsourceid").toString();
			// 获取sourcetype对应的字段
			List<Map<String, Object>> baseProperties = basePropertyService.getBaseProperty(sourceType,
					BASEPROPERTYSCOPE);
			if (baseProperties.size() <= 0) {
				return newVersion;
			}
			// 获取标题的baseProperty
			List<Map<String, Object>> basePropertiesFilter = baseProperties.stream()
					.filter(item -> item.get("sourcetype").toString().equals(sourceType)
							&& item.get("datatype").toString().equals(BaseSystemConst.BasePropertyDataTypeEnum.Title))
					.collect(Collectors.toList());
			if (basePropertiesFilter.size() <= 0) {
				return newVersion;
			}
			Map<String, Object> titleBaseProperty = basePropertiesFilter.get(0);
			// 获取当前表的是否有分类信息的分类字段
			String sourceKindKey = "";
			String kindTitle = "";
			if (titleBaseProperty.get("relationkind") != null
					&& !StringUtil.isEmpty(ConvertUtil.convertToString(titleBaseProperty.get("relationkind")))) {
				org.json.JSONArray kindJsonArray = new org.json.JSONArray(
						ConvertUtil.convertToString(titleBaseProperty.get("relationkind")));
				org.json.JSONObject jsonObject = kindJsonArray.getJSONObject(0);
				sourceKindKey = ConvertUtil.convertToString(jsonObject.get("kindkey"));
				if (!sourceKindKey.equals("") && newMap.containsKey(sourceKindKey)
						&& newMap.get(sourceKindKey) != null) {
					String kindValue = ConvertUtil.convertToString(newMap.get(sourceKindKey));
					for (int i = 0; i < kindJsonArray.length(); i++) {
						org.json.JSONObject obj = kindJsonArray.getJSONObject(i);
						if (ConvertUtil.convertToString(obj.get("kindvalue")).equals(kindValue)) {
							kindTitle = ConvertUtil.convertToString(obj.get("kindtitle"));
						}
					}
				}
			}
			// 组装变更记录数据
			JSONArray content = this.compareData(oldMap, newMap, baseProperties, baseLogOperateType);
			// 如果没有变更数据
			if (content.length() <= 0) {
				return newVersion;
			}
			// 企业客户、个人客户要更新version
			String allParentValues = "";
			List<String> versionArr = new ArrayList<String>(Arrays.asList("CpCustomerCompany", "CpCustomerPerson", "CpCustomerCompanyOther"));
			if (versionArr.contains(topsourcetype)) {
				Map<String, Object> customerInfo = this.getCustomerInfo(topsourcetype, topsourceid);
				newVersion = customerInfo.get("version").toString();
				//递归拼接ALlParentValues
				allParentValues = this.getAllParentValues(sourceType,sourceId,topsourcetype,topsourceid,newMap,versionArr);
			} else {
				newVersion = "0";
			}
			BaseChangeLogEntity baseChangeLogEntity = new BaseChangeLogEntity();
			baseChangeLogEntity.setSourcetype(sourceType);
			baseChangeLogEntity.setSourceid(sourceId);
			baseChangeLogEntity.setTopsourcetype(topsourcetype);
			baseChangeLogEntity.setTopsourceid(topsourceid);
			if (!StringUtil.isEmpty(newVersion)) {
				baseChangeLogEntity.setVersion(Integer.parseInt(newVersion));
			}
			try {
				baseChangeLogEntity.setTitle(this.getTitle(baseLogOperateType, kindTitle, titleBaseProperty, newMap));
			} catch (Exception e) {
				baseChangeLogEntity.setTitle("信息");
			}
			baseChangeLogEntity.setUsername(this.getSessionUserBean().getUser().getName());
			baseChangeLogEntity.setUsercode(this.getSessionUserBean().getUser().getCode());
			baseChangeLogEntity.setOperatetype(baseLogOperateType);
			baseChangeLogEntity.setContent(content.toString());
			// 如果存在sourceKindKey
			if (!sourceKindKey.equals("") && newMap.containsKey(sourceKindKey) && newMap.get(sourceKindKey) != null) {
				baseChangeLogEntity.setSourcekind(ConvertUtil.convertToString(newMap.get(sourceKindKey)));
			}
			if (inputMap.containsKey("description") && inputMap.get("description") != null) {
				baseChangeLogEntity.setDescription(inputMap.get("description").toString());
			}
			baseChangeLogEntity.setAllparentvalues(allParentValues);
			this.insert(baseChangeLogEntity);
			return newVersion;
		} catch (Exception e) {
			return newVersion;
		}
	}

	/**
	 * @Description: 根据入参查询不同客户表的历史记录, 更具创建时间倒叙排序
	 * @Author: mengmeng
	 * @Param: paraMap{ sourceType: sourceId: topSourceType: topSourceId: }
	 * @Return: List<BaseChangeLogEntity>
	 * @Date: 2020/12/8 19:31
	 */
	@Override
	public List<Map<String, Object>> queryChangeLogByOptions(Map<String, Object> paraMap) throws Exception {
		if (paraMap.isEmpty()) {
			throw new ServiceException("入参为空");
		}
		// 获取参数
		// BaseUtil.decodeSecureMap(paraMap);
		String sourceId = "";
		if (paraMap.containsKey("sourceId")) {
			sourceId = paraMap.get("sourceId").toString();
		}
		String sourceType = "";
		if (paraMap.containsKey("sourceType")) {
			sourceType = paraMap.get("sourceType").toString();
		}
		String topSourceType = "";
		if (paraMap.containsKey("topSourceType")) {
			topSourceType = paraMap.get("topSourceType").toString();
		}
		String topSourceId = "";
		if (paraMap.containsKey("topSourceId")) {
			topSourceId = paraMap.get("topSourceId").toString();
		}
		String sqlWhere = "";
		if (paraMap.containsKey("sqlWhere")) {
			sqlWhere = paraMap.get("sqlWhere").toString();
		}
		String sourceKind = "";
		if (paraMap.containsKey("sourceKind")) {
			sourceKind = paraMap.get("sourceKind").toString();
		}
		String parentValue = "";
		if (paraMap.containsKey("parentValue")) {
			parentValue = paraMap.get("parentValue").toString();
		}
		// 构造sql
		StringBufferProxy sql = new StringBufferProxy();
		if (!StringUtil.isEmpty(sqlWhere)) {
			sql.clear();
			getQuerySql(null, sourceType, topSourceType, topSourceId, sql, null, null);
			StringBufferProxy subSql = new StringBufferProxy();
			subSql.appendSingle(" {2} in ( select id from {0} where {1} ) and ", sourceType, sqlWhere,
					BaseChangeLogEntity.FieldSourceid);
			subSql.appendSingle(sql.toString());
			List<BaseChangeLogEntity> baseChangeLogEntities = this.queryByWhere(subSql.toString());
			// content内容字段转map类型
			return getContentMap(baseChangeLogEntities);
		} else {
			getQuerySql(sourceId, sourceType, topSourceType, topSourceId, sql, sourceKind, parentValue);
		}
		List<BaseChangeLogEntity> baseChangeLogEntities = this.queryByWhere(sql.toString());
		// content内容字段转map类型
		List<Map<String, Object>> maps = getContentMap(baseChangeLogEntities);
		return maps;
	}

	/**
	 * @Description: 根据年度计划表中的一条数据（一年）查询子表的该年下的所有记录的id
	 * @Author: mengmeng
	 * @Param: 每一年的id
	 * @Date: 2020/12/12 14:16
	 */
	private List<BaseChangeLogEntity> getAllChangeInOneYear(String sourceId, String sourceType, String topSourceType,
			String topSourceId) throws Exception {
		if (StringUtil.isEmpty(sourceId)) {
			throw new ServiceException("sourceId 不能为空");
		}
		// 获取sourceType关联的表
		List<Map<String, String>> relationTables = getRelationTables(sourceType);
		// 查取所有关联表的记录的变动历史
		List<BaseChangeLogEntity> changeLogList = new ArrayList<>();
		for (Map<String, String> relationTable : relationTables) {
			String relationSource = relationTable.get("relationsource");
			String relationKey = relationTable.get("relationkey");
			changeLogList.addAll(
					getChangeLogList(relationSource, relationKey, sourceId, sourceType, topSourceType, topSourceId));
		}
		// 查取主表的变动历史
		StringBufferProxy sqlWhere = new StringBufferProxy();
		getQuerySql(sourceId, sourceType, topSourceType, topSourceId, sqlWhere, null, null);
		List<BaseChangeLogEntity> baseChangeLogEntities = this.queryByWhere(sqlWhere.toString());
		changeLogList.addAll(baseChangeLogEntities);
		// 所有的历史记录按照创建时间倒叙排序
		Collections.sort(changeLogList, new Comparator<BaseChangeLogEntity>() {
			@Override
			public int compare(BaseChangeLogEntity o1, BaseChangeLogEntity o2) {
				if (o1.getCreateon().getTime() > o2.getCreateon().getTime()) {
					return -1;
				} else if (o1.getCreateon().getTime() < o2.getCreateon().getTime()) {
					return 1;
				} else {
					return 0;
				}
			}
		});
		return changeLogList;
	}

	private List<Map<String, String>> getRelationTables(String sourceType) throws Exception {
		List<Map<String, Object>> basePropertyList = basePropertyService.getBaseProperty(sourceType, BASEPROPERTYSCOPE);
		if (CollectionUtils.isEmpty(basePropertyList)) {
			throw new ServiceException("表 (" + sourceType + ") 没有需要记录历史的字段");
		}
		// 关联表
		List<Map<String, String>> relationTables = new ArrayList<>();
		Map<String, String> tableMap;
		for (Map<String, Object> map : basePropertyList) {
			tableMap = new HashMap<>();
			if (!map.containsKey("relationsource")) {
				continue;
			}
			String relationSource = map.get("relationsource").toString();
			if (StringUtil.isEmpty(relationSource)) {
				continue;
			}
			tableMap.putIfAbsent("relationsource", relationSource);
			tableMap.putIfAbsent("relationkey", map.get("relationkey").toString());
			relationTables.add(tableMap);
		}
		if (CollectionUtils.isEmpty(relationTables)) {
			throw new ServiceException("CpYearPlan表没有关联表");
		}
		return relationTables;
	}

	private List<BaseChangeLogEntity> getChangeLogList(String relationSource, String relationKey, String sourceId,
			String sourceType, String topSourceType, String topSourceId) {
		if (StringUtil.isEmpty(relationSource) || StringUtil.isEmpty(relationKey)) {
			throw new ServiceException("relationKey 字段不能为空");
		}
		StringBufferProxy sqlWhere = new StringBufferProxy();
		sqlWhere.appendSingle(relationKey + " = '{0}'", sourceId);
		String serviceName = relationSource.substring(0, 1).toLowerCase() + relationSource.substring(1) + "Service";
		BasicService baseService = (BasicService) SpringUtil.getBean(serviceName);
		List<Map<String, Object>> list = baseService.queryMapByWhere(sqlWhere.toString());
		List<String> ids = list.stream().map(map -> map.get("id").toString()).collect(Collectors.toList());
		if (CollectionUtils.isEmpty(ids)) {
			return new ArrayList<>();
		} else {
			getQuerySql(convertListToString(ids), relationSource, topSourceType, topSourceId, sqlWhere, null, null);
			return this.queryByWhere(sqlWhere.toString());
		}
	}

	private String convertListToString(List<String> list) {
		if (CollectionUtils.isEmpty(list)) {
			return "";
		}
		return list.stream().distinct().map(id -> "'" + id + "'").collect(Collectors.joining(","));
	}

	private List<Map<String, Object>> getContentMap(List<BaseChangeLogEntity> baseChangeLogEntities) {
		List<Map<String, Object>> maps = new ArrayList<>();
		for (BaseChangeLogEntity baseChangeLogEntity : baseChangeLogEntities) {
			String content = baseChangeLogEntity.getContent();
			Map<String, Object> map = baseChangeLogEntity.convertToMap();
			if ("[]".equals(content)) {
				map.put("displayContent", "");
				maps.add(map);
				continue;
			}
			org.json.JSONArray jsonArray = new org.json.JSONArray(content);
			List<Map<String, Object>> displayContentList = new ArrayList<>();
			for (int i = 0; i < jsonArray.length(); i++) {
				org.json.JSONObject jsonObject = jsonArray.getJSONObject(i);
				Map<String, Object> displayContent = jsonObject.toMap();
				displayContentList.add(displayContent);
			}
			map.put("displayContent", displayContentList);
			maps.add(map);
		}
		return maps;
	}

	private void getQuerySql(String sourceId, String sourceType, String topSourceType, String topSourceId,
			StringBufferProxy sql, String sourceKind, String parentValue) {
		sql.clear();
		sql.appendSingle(" 1 = 1 ");
		if (sourceId != null && !StringUtil.isEmpty(sourceId)) {
			if (!sourceId.contains("'")) {
				sourceId = "'" + sourceId + "'";
			}
			sql.appendSingle(" and " + BaseChangeLogEntity.FieldSourceid + " in ({0}) ", sourceId);
		}
		if (!StringUtil.isEmpty(sourceType)) {
			sql.appendSingle(" and " + BaseChangeLogEntity.FieldSourcetype + " = '{0}' ", sourceType);
		}
		if (!StringUtil.isEmpty(topSourceType)) {
			sql.appendSingle(" and " + BaseChangeLogEntity.FieldTopsourcetype + " = '{0}' ", topSourceType);
		}
		if (!StringUtil.isEmpty(topSourceId)) {
			sql.appendSingle(" and " + BaseChangeLogEntity.FieldTopsourceid + " = '{0}' ", topSourceId);
		}
		if (sourceKind != null && !StringUtil.isEmpty(sourceKind)) {
			if (sourceKind.contains("!=") || sourceKind.contains("is")) {
				sql.appendSingle(" and " + BaseChangeLogEntity.FieldSourcekind + " {0} ", sourceKind);
			} else {
				sql.appendSingle(" and " + BaseChangeLogEntity.FieldSourcekind + " = '{0}' ", sourceKind);
			}
		}
		if (!StringUtil.isEmpty(parentValue)) {
			sql.appendSingle(" or " + BaseChangeLogEntity.FieldAllparentvalues + " like '%{0}%' ", parentValue);
		}
		sql.appendSingle(" Order By " + BaseChangeLogEntity.FieldCreateon + " desc");
	}

	/**
	 * @param paraMap
	 * @return java.util.Map<java.lang.String, java.lang.Object>
	 * @description: 验证数据
	 * @author: wangxinhua
	 * @date: 2020/12/2 13:53
	 * @modify:
	 */
	private Map<String, Object> validateParams(Map<String, Object> paraMap) {
		Map<String, Object> resMap = new HashMap<String, Object>();
		List<String> validateArr = new ArrayList<String>(Arrays.asList("sourceid", "sourcetype", "newmap", "oldmap",
				"baselogoperatetype", "topsourcetype", "topsourceid"));
		for (String item : validateArr) {
			if (!paraMap.containsKey(item) || paraMap.get(item) == null
					|| StringUtil.isEmpty(paraMap.get(item).toString())) {
				resMap.put("success", false);
				resMap.put("msg", item + "不能为空！");
				return resMap;
			}
		}
		resMap.put("success", true);
		return resMap;
	}

	/**
	 * @param baselogoperatetype
	 * @param kindTitle
	 * @param titleBaseProperty
	 * @return java.lang.String
	 * @description: 获取标题
	 * @author: wangxinhua
	 * @date: 2020/12/2 18:46
	 * @modify:
	 */
	private String getTitle(String baselogoperatetype, String kindTitle, Map<String, Object> titleBaseProperty,
			Map<String, Object> newMap) {
		StringBuilder title = new StringBuilder();
		switch (baselogoperatetype) {
		case BaseSystemConst.BaseLogOperateTypeEnum.Add:
			title.append("新增");
			break;
		case BaseSystemConst.BaseLogOperateTypeEnum.Edit:
			title.append("编辑");
			break;
		case BaseSystemConst.BaseLogOperateTypeEnum.Del:
			title.append("删除");
			break;
		default:
			break;
		}
		title.append(" \"");
		title.append(parsingTitle(titleBaseProperty.get("name").toString(), newMap));
		if (!StringUtil.isEmpty(kindTitle)) {
			title.append("-");
			title.append(kindTitle);
		}
		title.append("\"");
		return title.toString();
	}

	/**
	 * @description: 解析带有{}的标题
	 * @param baseTitle
	 * @param newMap
	 * @return java.lang.String
	 * @author: wangxinhua
	 * @date: 2020/12/19 14:21
	 * @modify:
	 */
	private String parsingTitle(String baseTitle, Map<String, Object> newMap) {
		String regex = "\\{([^}])*\\}";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(baseTitle);
		ArrayList<String> replaceKeys = new ArrayList<String>();
		while (matcher.find()) {
			String key = matcher.group();
			String formatKey = key.replace("{", "");
			formatKey = formatKey.replace("}", "");
			if (newMap.containsKey(formatKey) && newMap.get(formatKey) != null) {
				baseTitle = baseTitle.replace(key, newMap.get(formatKey).toString());
			} else {
				baseTitle = baseTitle.replace(key, "");
			}
		}
		return baseTitle;
	}

	/**
	 * @param oldMap
	 * @param newMap
	 * @param baseProperties
	 * @param baselogoperatetype
	 * @return java.util.Map<java.lang.String, java.lang.Object>
	 * @description: 比较数据
	 * @author: wangxinhua
	 * @date: 2020/12/2 15:22
	 * @modify:
	 */
	@Override
	public JSONArray compareData(Map<String, Object> oldMap, Map<String, Object> newMap,
			List<Map<String, Object>> baseProperties, String baselogoperatetype) throws JSONException, ParseException {
		JSONArray contentJsonArr = new JSONArray();
		for (Map<String, Object> p : baseProperties) {
			String key = ConvertUtil.convertToString(p.get("code"));
			boolean isDateTime = false;
			// 确认是否是日期格式
			if (BaseSystemConst.BasePropertyDataTypeEnum.Datetime.equals(p.get("datatype"))) {
				isDateTime = true;
			}
			if (oldMap.containsKey(key) && newMap.containsKey(key)) {
				JSONObject json = new JSONObject();
				json.put("code", p.get("code"));
				json.put("name", p.get("name"));
				if (isDateTime) {
					String oldTime = ConvertUtil.convertToString(oldMap.get(key));
					String newTime = ConvertUtil.convertToString(newMap.get(key));
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					if (!StringUtil.isEmpty(oldTime) && !oldTime.contains("-") && !oldTime.contains(":")) {
						String d_timestamp = sdf.format(new Date(Long.parseLong(ConvertUtil.convertToString(oldTime))));
						oldMap.put(key, d_timestamp);
					}
					if (oldTime.contains(".")) {
						String d_timestamp = oldTime.substring(0, oldTime.indexOf("."));
						;
						oldMap.put(key, d_timestamp);
					}
					if ((!StringUtil.isEmpty(newTime) && !newTime.contains("-") && !newTime.contains(":"))) {
						String d_timestamp = sdf.format(new Date(Long.parseLong(ConvertUtil.convertToString(newTime))));
						newMap.put(key, d_timestamp);
					} else {
						if (newTime.length() == 10) {
							String d_timestamp = newTime + " 00:00:00";
							newMap.put(key, d_timestamp);
						}
					}
					if (newTime.contains(".")) {
						String d_timestamp = newTime.substring(0, newTime.indexOf("."));
						;
						newMap.put(key, d_timestamp);
					}
				}
				// 是否编码字段
				boolean isCodeField = false;
				// 使用代码表的编码
				if (!StringUtil.isEmpty(ConvertUtil.convertToString(p.get("inputcode")))) {
					isCodeField = true;
					List<Map<String, Object>> inputCodeList = datacodeCache
							.getCodeListMap(ConvertUtil.convertToString(p.get("inputcode")), "", "sortcode");
					List<Map<String, Object>> oldCodes = inputCodeList.stream()
							.filter(item -> item.get("code").equals(ConvertUtil.convertToString(oldMap.get(key))))
							.collect(Collectors.toList());
					if (oldCodes.size() > 0) {
						oldMap.put("disp" + key, oldCodes.get(0).get("name"));
					}
					List<Map<String, Object>> newCodes = inputCodeList.stream()
							.filter(item -> item.get("code").equals(ConvertUtil.convertToString(newMap.get(key))))
							.collect(Collectors.toList());
					if (newCodes.size() > 0) {
						newMap.put("disp" + key, newCodes.get(0).get("name"));
					}
				}
				if (baselogoperatetype.equals(BaseSystemConst.BaseLogOperateTypeEnum.Add)) {
					// 如果是增加不添加旧数据
					if (isCodeField) {
						json.put("new", newMap.get("disp" + key));
					} else {
						json.put("new", ConvertUtil.convertToString(newMap.get(key)));
					}
					contentJsonArr.put(json);
				} else if (baselogoperatetype.equals(BaseSystemConst.BaseLogOperateTypeEnum.Del)) {
					// 如果是删除不添加新数据
					if (isCodeField) {
						json.put("old", oldMap.get("disp" + key));
					} else {
						json.put("old", ConvertUtil.convertToString(oldMap.get(key)));
					}
					contentJsonArr.put(json);
				} else {
					if (!ConvertUtil.convertToString(oldMap.get(key))
							.equals(ConvertUtil.convertToString(newMap.get(key)))) {
						if (isCodeField) {
							json.put("new", newMap.get("disp" + key));
						} else {
							json.put("new", ConvertUtil.convertToString(newMap.get(key)));
						}
						if (isCodeField) {
							json.put("old", oldMap.get("disp" + key));
						} else {
							json.put("old", ConvertUtil.convertToString(oldMap.get(key)));
						}
						contentJsonArr.put(json);
					}
				}
			}
		}
		return contentJsonArr;
	}

	/**
	 * @description: 获取客户信息并更新version
	 * @param topsourcetype
	 * @param topsourceid
	 * @return java.util.Map<java.lang.String, java.lang.Object>
	 * @description: 获取客户信息并更新version
	 * @author: wangxinhua
	 * @date: 2020/12/11 15:47
	 * @modify:
	 */
	private Map<String, Object> getCustomerInfo(String topsourcetype, String topsourceid) {
		Map<String, Object> customerInfo = new HashMap<String, Object>();
		// 企业客户、个人客户要更新version
		// 是否在更新version
		IBasicDao basicDao;
		String serviceName = topsourcetype.substring(0, 1).toLowerCase() + topsourcetype.substring(1) + "Dao";
		basicDao = (IBasicDao) SpringUtil.getBean(serviceName);
		List<Map<String, Object>> customerList = basicDao.queryMapByWhere(" code = '" + topsourceid + "'");
		customerInfo = customerList.get(0);
		int newVersion = Integer.parseInt(customerInfo.get("version").toString()) + 1;
		customerInfo.put("version", newVersion);
		basicDao.update(customerInfo);
		return customerInfo;
	}

	private String getAllParentValues(String sourceType, String sourceId, String topsourcetype, String topsourceid,
			Map<String, Object> newMap, List<String> versionArr) throws Exception {
		StringBuffer allParentValuesStr = new StringBuffer();
		List<Map<String, Object>> allProperties = basePropertyService.getBaseProperty("AllProperty", BASEPROPERTYSCOPE);
		List<Map<String, Object>> relationSourceList = allProperties.stream()
				.filter(item -> sourceType.equals(ConvertUtil.convertToString(item.get("relationsource")))
						&& ConvertUtil.convertToString(item.get("relationkind"))
								.contains(ConvertUtil.convertToString(newMap.get("sourcetype"))))
				.collect(Collectors.toList());
		List<Map<String, Object>> parents = new ArrayList<Map<String, Object>>();
		if (relationSourceList.size() > 0) {
			this.getParentProperty(relationSourceList.get(0), allProperties, parents, newMap, versionArr);
		}
		if (parents.size() > 0) {
			for (Map<String, Object> p : parents) {
				allParentValuesStr.append(",");
				allParentValuesStr.append(p.get("parentkeystr"));
			}
			allParentValuesStr.append(",");
		}
		return allParentValuesStr.toString();
	}

	private void getParentProperty(Map<String, Object> relationSourceProperty, List<Map<String, Object>> allProperties,
			List<Map<String, Object>> allParents, Map<String, Object> ownData, List<String> versionArr) {
		if (!StringUtil.isEmpty(ConvertUtil.convertToString(relationSourceProperty.get("relationsource")))) {
			List<Map<String, Object>> parentSources = allProperties.stream()
					.filter(item -> ConvertUtil.convertToString(relationSourceProperty.get("sourcetype"))
							.equals(ConvertUtil.convertToString(item.get("relationsource"))))
					.collect(Collectors.toList());
			if (!versionArr.contains(ConvertUtil.convertToString(relationSourceProperty.get("sourcetype")))) {
				IBasicDao basicDao;
				String serviceName = relationSourceProperty.get("sourcetype").toString().substring(0, 1).toLowerCase()
						+ relationSourceProperty.get("sourcetype").toString().substring(1) + "Dao";
				basicDao = (IBasicDao) SpringUtil.getBean(serviceName);
				List<Map<String, Object>> queryList = basicDao.queryMapByWhere(" id = '"
						+ ConvertUtil.convertToString(ownData.get(relationSourceProperty.get("relationkey"))) + "'");
				if (queryList.size() > 0) {
					Map<String, Object> parentData = queryList.get(0);
					parentData.put("parentkeystr", ConvertUtil.convertToString(relationSourceProperty.get("sourcetype"))
							+ ConvertUtil.convertToString(parentData.get("id")));
					allParents.add(parentData);
					if (parentSources.size() > 0) {
						getParentProperty(parentSources.get(0), allProperties, allParents, parentData, versionArr);
					}
				}
			}
		}
	}

	/**
	 *
	 * @description:记录主表变更记录,确定是更新再调用
	 * @param backboneEntity
	 * @return
	 * @author: hdy
	 * @date: 2022年4月27
	 * @modify:
	 */
	@Override
	public boolean isSaveChangeLog(Map<String, Object> map,String tableName,String newVersion) {
		// 判断是否为新增
		boolean ischanged;
		Map<String, Object> changeMap = new HashMap<String, Object>();
		changeMap.put("sourceid", map.get("id"));
		changeMap.put("sourcetype", tableName);
		changeMap.put("topsourcetype", tableName);
		changeMap.put("topsourceid", map.get("id"));
		changeMap.put("newmap", map);
		changeMap.put("baselogoperatetype", BaseLogOperateTypeEnum.Edit);
		StringBufferProxy sql = new StringBufferProxy();
		sql.appendSingle("select * from {0} where id = '{1}'", tableName,map.get("id"));
		List<Map<String, Object>> oldEntities = this.selectExecute(sql.toString());
		if(oldEntities.size() == 0) {
			return false;
		}
		changeMap.put("oldmap", oldEntities.get(0));
		ischanged = this.insertChangeLogForAll(changeMap, tableName,newVersion);
		return ischanged;
	}

	/**
	 *
	 * @description:记录主表变更记录
	 * @param backboneEntity
	 * @return
	 * @author: hdy
	 * @date: 2022年4月27日
	 * @modify:
	 */
	protected boolean insertChangeLogForAll(Map<String, Object> inputMap, String tableName, String newVersion) {
		// 返回是否更新，产生changelog
		try {
			// 验证参数
			Map<String, Object> validateMap = validateParams(inputMap);
			if (validateMap.get("success").equals(false)) {
				return false;
			}
			// 整理变量类型
			Map<String, Object> newMap = (Map<String, Object>) inputMap.get("newmap");
			Map<String, Object> oldMap = (Map<String, Object>) inputMap.get("oldmap");
			String sourceType = inputMap.get("sourcetype").toString();
			String sourceId = inputMap.get("sourceid").toString();
			String baseLogOperateType = inputMap.get("baselogoperatetype").toString();
			String topsourcetype = inputMap.get("topsourcetype").toString();
			String topsourceid = inputMap.get("topsourceid").toString();
			// 获取sourcetype对应的字段
			List<Map<String, Object>> baseProperties = basePropertyService.getBaseProperty(sourceType,
					BASEPROPERTYSCOPE);
			if (baseProperties.size() <= 0) {
				return false;
			}
			// 获取标题的baseProperty
			List<Map<String, Object>> basePropertiesFilter = baseProperties.stream()
					.filter(item -> item.get("sourcetype").toString().equals(sourceType)
							&& item.get("datatype").toString().equals(BaseSystemConst.BasePropertyDataTypeEnum.Title))
					.collect(Collectors.toList());
			if (basePropertiesFilter.size() <= 0) {
				return false;
			}
			Map<String, Object> titleBaseProperty = basePropertiesFilter.get(0);
			// 获取当前表的是否有分类信息的分类字段
			String sourceKindKey = "";
			String kindTitle = "";
			if (titleBaseProperty.get("relationkind") != null
					&& !StringUtil.isEmpty(ConvertUtil.convertToString(titleBaseProperty.get("relationkind")))) {
				org.json.JSONArray kindJsonArray = new org.json.JSONArray(
						ConvertUtil.convertToString(titleBaseProperty.get("relationkind")));
				org.json.JSONObject jsonObject = kindJsonArray.getJSONObject(0);
				sourceKindKey = ConvertUtil.convertToString(jsonObject.get("kindkey"));
				if (!sourceKindKey.equals("") && newMap.containsKey(sourceKindKey)
						&& newMap.get(sourceKindKey) != null) {
					String kindValue = ConvertUtil.convertToString(newMap.get(sourceKindKey));
					for (int i = 0; i < kindJsonArray.length(); i++) {
						org.json.JSONObject obj = kindJsonArray.getJSONObject(i);
						if (ConvertUtil.convertToString(obj.get("kindvalue")).equals(kindValue)) {
							kindTitle = ConvertUtil.convertToString(obj.get("kindtitle"));
						}
					}
				}
			}
			// 组装变更记录数据
			JSONArray content = this.compareData(oldMap, newMap, baseProperties, baseLogOperateType);
			// 如果没有变更数据
			if (content.length() <= 0) {
				return false;
			}
			BaseChangeLogEntity baseChangeLogEntity = new BaseChangeLogEntity();
			baseChangeLogEntity.setSourcetype(sourceType);
			baseChangeLogEntity.setSourceid(sourceId);
			baseChangeLogEntity.setTopsourcetype(topsourcetype);
			baseChangeLogEntity.setTopsourceid(topsourceid);
			if (!StringUtil.isEmpty(newVersion)) {
				baseChangeLogEntity.setVersion(Integer.parseInt(newVersion));
			}
			try {
				baseChangeLogEntity.setTitle(this.getTitle(baseLogOperateType, kindTitle, titleBaseProperty, newMap));
			} catch (Exception e) {
				baseChangeLogEntity.setTitle("信息");
			}
			baseChangeLogEntity.setUsername("");
			baseChangeLogEntity.setUsercode("");
			baseChangeLogEntity.setOperatetype(baseLogOperateType);
			baseChangeLogEntity.setContent(content.toString());
			// 如果存在sourceKindKey
			if (!sourceKindKey.equals("") && newMap.containsKey(sourceKindKey) && newMap.get(sourceKindKey) != null) {
				baseChangeLogEntity.setSourcekind(ConvertUtil.convertToString(newMap.get(sourceKindKey)));
			}
			if (inputMap.containsKey("description") && inputMap.get("description") != null) {
				baseChangeLogEntity.setDescription(inputMap.get("description").toString());
			}
			this.insert(baseChangeLogEntity);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	// 保存basechangelog
	public void insertLogMap(Map<String, Object> logMap) {
		BaseChangeLogEntity baseChangeLogEntity = new BaseChangeLogEntity();
		this.insert(baseChangeLogEntity.convertFromMap(logMap));
	}
	/**
	 *
	 * @description:销售项目使用数据比较接口
	 * @return
	 * @author: houyuhang
	 * @date: 2023年02月06日
	 * @modify:
	 */
	public String compareDataForMpm(Map<String, Object> oldMap, Map<String, Object> newMap,
								 List<Map<String, Object>> baseProperties, String baselogoperatetype) throws JSONException, ParseException {
		JSONArray jsonArray = this.compareData(oldMap, newMap, baseProperties, baselogoperatetype);
		return jsonArray.toString();
	}
}
